﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ComputerArchitecture.Core;
using ComputerArchitecture.Core.Logging;
using ComputerArchitecture.Numbers;
using ComputerArchitecture.Units.Integers.Unsigned.Interfaces;

namespace ComputerArchitecture.Units.Integers.Unsigned.Implementations
{
    public class UnsignedSubstractUnit : LoggingObject, IUnsignedSubstractUnit
    {
        public UnsignedSubstractUnit(ILoggingService loggingService) : base(loggingService)
        {
        }

        IBitNumber ISubstractUnit.Substract(IBitNumber first, IBitNumber second, out bool overflow)
        {
            return this.Substract((IUnsignedBitNumber) first, (IUnsignedBitNumber) second, out overflow);
        }

        public IUnsignedBitNumber Substract(IUnsignedBitNumber first, IUnsignedBitNumber second, out bool overflow)
        {
            ArgumentValidator.NullValidate(first, "first");
            ArgumentValidator.NullValidate(second, "second");
            if (first.Size != second.Size)
            {
                throw new IncompatibleSizeException();
            }
            IUnsignedBitNumber result = new UnsignedBitNumber(first.Size);
            Bit carryBit = Bit.One;
            for (int i = first.Size - 1; i >= 0; --i)
            {
                result[i] = FullAdder.Add(first[i], !second[i], carryBit, out carryBit);
            }
            overflow = carryBit.IsSet;
            return result;
        }

        public IUnsignedBitNumber Dec(IUnsignedBitNumber value, out bool overflow)
        {
            IUnsignedBitNumber one = new UnsignedBitNumber(value.Size);
            one.Last().Set();
            return this.Substract(value, one, out overflow);
        }
    }
}
